///////////////////////////////////////////////////////////////////////////////
//
//  Copyright
//
///////////////////////////////////////////////////////////////////////////////

package ru.goodcore.utils
{

import flash.xml.XMLDocument;
import flash.xml.XMLNode;
import flash.xml.XMLNodeType;

/**
 * The StringUtil utility class is an all-static class with methods for
 * working with String objects within GoodCore.
 * You should do not create instances of StringUtil. Call methods such as 
 * the <code>StringUtil.substitute()</code> instead.
 * 
 * @author					Dimarik
 * @version					1.0
 * @playerversion			Flash 9
 * @langversion				3.0
 *
 * @keyword					stringutils, string
 */
public final class StringUtils {

	//-------------------------------------------------------------------------
	//
	//  Class methods
	//
	//-------------------------------------------------------------------------

	/**
	 * Converts a string so that it has html entities
	 * @param text
	 * @return 
	 * 
	 */	
	public static function decodeHTML(str:String):String {
		return new XMLDocument(str).firstChild.nodeValue;
	}


	/**
	 * Converts a string with html entities (such as &amp;) to their respective symbols
	 * @param text
	 * @return 
	 * 
	 */
	public static function encodeHTML(str:String):String {
		return XML( new XMLNode( XMLNodeType.TEXT_NODE, str ) ).toXMLString();
	}


	/**
	 *  Removes all whitespace characters from the beginning and end
	 *  of the specified string.
	 *
	 *  @param str The String whose whitespace should be trimmed. 
	 *
	 *  @return Updated String where whitespace was removed from the 
	 *  beginning and end. 
	 */
	private static const _TRIM_PATTERN:	RegExp = /^\s*|\s*$/g;

	public static function trim(text:String):String {
		return text.replace(_TRIM_PATTERN, '');
	}

	/**
	 *  Removes all whitespace characters from the beginning and end
	 *  of each element in an Array, where the Array is stored as a String. 
	 *
	 *  @param value The String whose whitespace should be trimmed. 
	 *
	 *  @param separator The String that delimits each Array element in the string.
	 *
	 *  @return Updated String where whitespace was removed from the 
	 *  beginning and end of each element. 
	 */
	public static function trimArrayElements(value:String, delimiter:String):String {
		if (value != '' && value != null) {
			var items:Array = value.split(delimiter);

			var len:uint = items.length;
			for (var i:uint = 0; i < len; i++) 
				items[i] = StringUtils.trim(items[i]);

			if (len > 0)
				value = items.join(delimiter);
		}

		return value;
	}
	/**
	 * Converts from camelStyleNoUnderscores to ALL_UPPER_CASE_WITH_UNDERSCORES
	 * 
	 * @see 	ru.goodcore.utilsStringUtils#convertToConstName
	 * 
	 * @param 	name 	String to convert
	 * @return 	Converted string
	 * 
	 */
	public static function convertToConstName(value:String):String {
		return value.match( /\w[^A-Z]*/g ).join("_").toUpperCase();
	}

	/**
	 * Converts from ALL_UPPER_CASE_WITH_UNDERSCORES to camelStyleNoUnderscores
	 * 
	 * @see 	ru.goodcore.utilsStringUtils#convertFromConstName
	 * 
	 * @param 	name 	String to convert
	 * @return 	Converted string
	 * 
	 */
	public static function convertFromConstName(value:String):String {
		var arr:		Array = value.split("_");
		var result:		String = ( arr.shift() as String ).toLowerCase();
		for each (var word:String in arr)
			result += word.charAt(0).toUpperCase() + word.substr(1).toLowerCase();

		return result;
	}

	/**
	 *  Returns <code>true</code> if the specified string is
	 *  a single space, tab, carriage return, newline, or formfeed character.
	 *
	 *  @param str The String that is is being queried. 
	 *
	 *  @return <code>true</code> if the specified string is
	 *  a single space, tab, carriage return, newline, or formfeed character.
	 */
	public static function isWhitespace(character:String):Boolean {
		switch (character) {
			case " ":
			case "\t":
			case "\r":
			case "\n":
			case "\f":
				return true;

			default:
				return false;
		}
	}

	/**
	 *  Substitutes "{n}" tokens within the specified string
	 *  with the respective arguments passed in.
	 *
	 *  @param str The string to make substitutions in.
	 *  This string can contain special tokens of the form
	 *  <code>{n}</code>, where <code>n</code> is a zero based index,
	 *  that will be replaced with the additional parameters
	 *  found at that index if specified.
	 *
	 *  @param rest Additional parameters that can be substituted
	 *  in the <code>str</code> parameter at each <code>{n}</code>
	 *  location, where <code>n</code> is an integer (zero based)
	 *  index value into the array of values specified.
	 *  If the first parameter is an array this array will be used as
	 *  a parameter list.
	 *  This allows reuse of this routine in other methods that want to
	 *  use the ... rest signature.
	 *  For example <pre>
	 *     public function myTracer(str:String, ... rest):void {
	 *         label.text += StringUtil.substitute(str, rest) + "\n";
	 *     } </pre>
	 *
	 *  @return New string with all of the <code>{n}</code> tokens
	 *  replaced with the respective arguments specified.
	 *
	 *  @example
	 *
	 *  var str:String = "here is some info '{0}' and {1}";
	 *  trace(StringUtil.substitute(str, 15.4, true));
	 *
	 *  // this will output the following string:
	 *  // "here is some info '15.4' and true"
	 */
	public static function substitute(str:String, ... rest):String {
		if (str == null) return '';

		// Replace all of the parameters in the msg string.
		var len:	uint = rest.length;
		var args:	Array;
		if (len == 1 && rest[0] is Array) {
			args = rest[0] as Array;
			len = args.length;
		}
		else {
			args = rest;
		}

		for (var i:uint = 0; i < len; i++)
			str = str.replace(new RegExp('\\{' + i + '\\}', 'g'), args[i]);

		return str;
	}

	/**
	*  Приводит число к виду 000i, где len - результирующее кол-во знаков
	*
	*  @param	i		число для преобразования
	*  @param	len		результирующее количество знаков
	*/
	public static function setNumberLen(
										i:uint, len:uint = 3, radix:uint = 10, 
										fill:String='0'):String {
		var s:String = i.toString(radix);
		while (s.length < len) s = fill + s;
		return s;
	}

}
}
